﻿using HenuAlbum.ControllerModels;
using HenuAlbum.DbContext;
using HenuAlbum.Models;
using HenuAlbum.ResponseModels;
using HenuAlbum.Utils;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using SixLabors.ImageSharp;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;

namespace HenuAlbum.Controllers
{
    [ApiController]
    [Route("api/[controller]")]
    public class CarouselController : ControllerBase
    {
        private readonly AppDbContext _appDbContext;

        public CarouselController(AppDbContext appDbContext)
        {
            _appDbContext = appDbContext;
        }

        [HttpGet]
        public async Task<IActionResult> GetCarousel()
        {
            var list = await _appDbContext.Carousel.AsNoTracking().Select(x => new
            {
                x.Id,
                x.FileName,
                x.Rank
            }).OrderByDescending(x => x.Rank).Take(5).ToListAsync();

            return Ok(new ArrayResponse(list));
        }

        [Authorize]
        [Authorize(Roles = "管理员")]
        [HttpPost("Upload")]
        public async Task<IActionResult> UploadCarousel(IFormFile file)
        {
            if (file == null || file.Length == 0)
            {
                return BadRequest(new IncorrectError("文件内容不可为空!"));
            }

            try
            {
                var imageInfo = Image.Identify(file.OpenReadStream());
                if (imageInfo == null)
                {
                    return BadRequest(new IncorrectError("图片已损坏, 无法解析."));
                }
            }
            catch (Exception ex)
            {
                // TODO: log
                return BadRequest(new IncorrectError("图片已损坏, 无法解析."));
            }

            string savePath = Constants.CarouselImagesPath;
            string fileExtention = Path.GetExtension(file.FileName).Substring(1);
            string filePath = null;

            // 生成储存到硬盘的文件名称
            string diskFileName = null;
            do
            {
                diskFileName = $"{Guid.NewGuid():D}.{fileExtention}";
                filePath = Path.Combine(savePath, diskFileName);
            } while (System.IO.File.Exists(filePath));

            // 保存文件到磁盘
            Task saveFileTask = null;
            using Stream fileStream = new FileStream(filePath, FileMode.Create);
            saveFileTask = file.CopyToAsync(fileStream);

            var c = new Carousel()
            {
                FileName = diskFileName,
                Rank = 0
            };
            _appDbContext.Carousel.Add(c);
            await _appDbContext.SaveChangesAsync();
            await saveFileTask;

            return Ok(new OkResponse() { Data = c });
        }

        [Authorize]
        [Authorize(Roles = "管理员")]
        [HttpPost("UpdateRank")]
        public async Task<IActionResult> UpdateRank(UpdateCarouselRank param)
        {
            var c = await _appDbContext.Carousel.Where(x => x.Id == param.Id).FirstOrDefaultAsync();
            if (c == null)
            {
                return BadRequest(new NotExistsError("轮播图不存在!"));
            }
            c.Rank = param.Rank;
            await _appDbContext.SaveChangesAsync();
            return Ok(new OkResponse() { Data = c });
        }

        [Authorize]
        [Authorize(Roles = "管理员")]
        [HttpPost("{id:int}/Remove")]
        public async Task<IActionResult> RemoveCarousel(int id)
        {
            var c = await _appDbContext.Carousel.Where(x => x.Id == id).FirstOrDefaultAsync();
            if (c == null)
            {
                return BadRequest(new NotExistsError("轮播图不存在!"));
            }
            string filePath = Path.Combine(Constants.CarouselImagesPath, c.FileName);
            if (System.IO.File.Exists(filePath))
            {
                System.IO.File.Delete(filePath);
            }
            _appDbContext.Carousel.Remove(c);
            await _appDbContext.SaveChangesAsync();
            return Ok(new OkResponse());
        }

    }
}
